import 'package:dio/dio.dart';
import 'package:smart_ai_dart/utils/log_utils.dart';
import 'package:smart_ai_dart/utils/storage.dart';

class HttpUtils {
  bool _isInitialized = false;
  late Dio dio;
  static const String _tokenKey = 'jwt_token';
  static final HttpUtils shared = HttpUtils._internal();

  factory HttpUtils() {
    return shared;
  }

  HttpUtils._internal();

  // Get JWT token from storage
  String? get _token => StorageUtils.shared.getString(_tokenKey);

  // Set JWT token to storage
  Future<void> setToken(String token) async {
    await StorageUtils.shared.setString(_tokenKey, token);
  }

  // Clear JWT token
  Future<void> clearToken() async {
    await StorageUtils.shared.remove(_tokenKey);
  }

  Future<void> init({String? baseUrl}) async {
    if (_isInitialized) {
      LogUtils.shared.w('HttpUtils has already been initialized!');
      return;
    }

    BaseOptions options = BaseOptions(
      baseUrl: baseUrl ?? 'https://api.example.com',
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 10),
      headers: {
        'Content-Type': 'application/json',
      },
    );

    dio = Dio(options);

    // Add interceptors
    dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        // Add JWT token to header if exists
        final token = _token;
        if (token != null && token.isNotEmpty) {
          options.headers['Authorization'] = 'Bearer $token';
          LogUtils.shared.d('Added JWT token to request');
        }

        LogUtils.shared.i('Headers: ${options.headers}');
        LogUtils.shared.i('Data: ${options.data}');
        LogUtils.shared.i('Request: ${options.method} ${options.uri}');
        return handler.next(options);
      },
      onResponse: (response, handler) {
        // Check for new token in response headers
        final newToken = response.headers.value('Authorization');
        if (newToken != null) {
          setToken(newToken.replaceFirst('Bearer ', ''));
          LogUtils.shared.d('Updated JWT token from response');
        }

        LogUtils.shared.i('Response: ${response.statusCode}');
        LogUtils.shared.i('Response data: ${response.data}');
        return handler.next(response);
      },
      onError: (error, handler) {
        // Handle authentication errors
        if (error.response?.statusCode == 401) {
          LogUtils.shared.w('Authentication failed, clearing token');
          clearToken();
          // You might want to trigger a logout or token refresh here
        }

        LogUtils.shared.e('Error: ${error.message}');
        return handler.next(error);
      },
    ));

    _isInitialized = true;
    LogUtils.shared.i('HttpUtils initialized successfully');
  }

  // Check initialization
  void _checkInitialization() {
    if (!_isInitialized) {
      throw Exception(
          'HttpUtils has not been initialized. Call HttpUtils.shared.init() first.');
    }
  }

  // GET request
  Future<Response> get(
    String path, {
    Map<String, dynamic>? params,
    bool requireAuth = true,
  }) async {
    _checkInitialization();
    if (requireAuth && _token == null) {
      throw Exception('Authentication required');
    }
    try {
      return await dio.get(path, queryParameters: params);
    } catch (e) {
      LogUtils.shared.e('GET Error: $e');
      rethrow;
    }
  }

  // POST request
  Future<Response> post(
    String path, {
    dynamic data,
    bool requireAuth = true,
  }) async {
    _checkInitialization();
    if (requireAuth && _token == null) {
      throw Exception('Authentication required');
    }
    try {
      return await dio.post(path, data: data);
    } catch (e) {
      LogUtils.shared.e('POST Error: $e');
      rethrow;
    }
  }

  // PATCH request
  Future<Response> patch(
    String path, {
    dynamic data,
    bool requireAuth = true,
  }) async {
    _checkInitialization();
    if (requireAuth && _token == null) {
      throw Exception('Authentication required');
    }
    try {
      return await dio.patch(path, data: data);
    } catch (e) {
      LogUtils.shared.e('PATCH Error: $e');
      rethrow;
    }
  }
}
